/* 
 * File:   Images.h
 * Author: ungerma
 *
 * Created on 04. August 2014, 14:15
 */

#ifndef IMAGES_H
#define	IMAGES_H

#include <dirent.h>
#include <cstdio>
#include <exception>
#include <stdexcept>
#include <cstdlib>
#include <iostream>
#include <vector>
#include <fstream>
#include <string>

#include "opencv2/opencv.hpp"

#include "SingleImage.h"
#include "TestResults.h"
#include "HOGSettings.h"

using namespace cv;
using namespace std;

enum ImageParsing {
    
    UNCHANGED = 0, N_RANDOM_WINDOWS = 1, CROP_FROM_MARGIN = 2,
    RESIZE_TO_ANNOTATION = 3, SCALE_SPACE_WINDOW = 4
    
};

class Images {
public:
    
    Images(HOGSettings settings);
    
    void readTrain(String posTrainPath, String negTrainPath, String featureFile,
        string mpeg7List, string mpeg7Path, string mpegScd, string mpegEhd);
    void readTest(String posTestPath, String negTestPath, String featureFile,
        string mpeg7List, string mpeg7Path, string mpegScd, string mpegEhd,
        string nameFile);
    static void debugWindow(Mat image, string absolutePath);
    
    vector<SingleImage> getPosTrain();
    vector<SingleImage> getNegTrain();
    vector<SingleImage> getPosTest();
    vector<SingleImage> getNegTest();
    
    /*
     * Images size for positive training samples.
     * Negative training samples are cropped randomly to this size.
     */
    static const int POS_TRAINING_WIDTH = 64;
    static const int POS_TRAINING_HEIGHT = 128;
     
    /*
     * For parsing mode CROP_FROM_MARGIN.
     * Actual persons have this margin around them.
     */
    static const int POS_TRAINING_MARGIN = 16;
    
    /*
     * For parsing mode N_RANDOM_WINDOWS.
     * From negative training images, we take that many random samples.
     */
    static const int NUMBER_RANDOM_WINDOWS = 1;
    
    /*
     * For parsing mode N_RANDOM_WINDOWS.
     * For repeatable random window generation.
     */
    static const int RANDOM_SEED = 12956;
    
    /*
     * For parsing mode SCALE_SPACE_WINDOW.
     * For sliding image image preprocessing.
     */
    static const int SLIDING_WINDOW_X = POS_TRAINING_WIDTH;
    static const int SLIDING_WINDOW_Y = POS_TRAINING_HEIGHT;
    
    /*
     * For parsing mode SCALE_SPACE_WINDOW.
     * Image is resized by this factor.
     */
    static const float SCALE_SPACE_FACTOR = 1.5;
    
    /*
     * For parsing mode RESIZE_TO_ANNOTATION.
     * We have to cut our test images to size. We add this margin to the
     * bounding boxes.
     */
    static const int BOUNDING_MARGIN = 16;
    
    /*
     * Limit for positive classification of a window.
     * y > LIMIT => y is class A.
     * else      => y is class B.
     * If you generate many windows per test image, this should be high 
     * (i.e. much larger than 0).
     * If you generate few windows per test image, this should be low
     * (i.e. close to 0).
     */
    static const float LIMIT = 0.0;
    
    /*
     * Minimal and maximal possible classification score y.
     */
    static const float MIN_Y = -9999;
    static const float MAX_Y =  9999;
    
protected:
    
    void readImagesInDir(vector <SingleImage>& images,
            string dir, enum ImageParsing, float groundTruth, string featureFile,
            string mpeg7List, string mpeg7Path, string mpegScd, string mpegEhd,
            string nameFile);
    void readImagesInDirNoFeatureVecotrs(vector <SingleImage>& res, string dirName,
        ImageParsing p, float groundTruth, string nameFile);
    void writeFilelist(string filename, string targetfile);
    void exceptionIfWrongSize(Mat i, String absolutePath);
    void exceptionIfWrongSize(Rect r, String absolutePath);
    Mat resizeToAnnotation(Mat i, string relPath, string dir);
    void addScaleSpaceWindows(SingleImage* si, Mat image);
    
    vector <SingleImage> posTrain, negTrain, posTest, negTest;
    HOGSettings settings;
};

#endif	/* IMAGES_H */
